/******************************************************************************
MSP430g2553 Generic I2C slave PWM peripheral

This code does two things:
1)	Blinks an LED on P1.0 on and off with a period of 1 second

2)	Uses the generic I2C slave code to implement an I2C peripheral with 
	2x 8-bit PWM channels.

The I2C protocol is as follows:
register	r/w?	function
0x00		r/w		PWM enable.  Bitmask for PWM channel enable bits (2 LSB).
0x01		r/w		PWM channel 1 value, 0 -> always off, 255 -> always on
0x02		r/w		PWM channel 2 value
*******************************************************************************/

#include "msp430g2553.h"
#include "i2c_slave.h"
#include "heartbeat.h"
#include "util.h"

#define	I2C_OWN_ADDR	0x20		// address 0x40 -> we receive from master, 0x41 -> we write byte to I2C bus

unsigned char	i2cdata = 0x00;	// scratch pad for playing with i2c info

#define	NUM_REG	3
unsigned char registers[NUM_REG];

void main(void) {
	
	// stop the watchdog timer
	WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
	
	// set up internal clocking
	if (CALBC1_16MHZ ==0xFF || CALDCO_16MHZ == 0xFF) while(1);	// set up to use internal oscillator                                             
	DCOCTL = CALDCO_16MHZ;                		// Set uC to run at approximately 16 Mhz
	BCSCTL1 = CALBC1_16MHZ; 
	
	
	// Timer A1 config - PWM
	// set up timer A1 to have period of ~8KHz, 255 step resolution (2MHz update)
	TA1CCR0 = 255;				// ~8KHz period, we use /8 clock divider
	TA1CCR1 = TA1CCR2 = 0;		// set both off
	TA1CTL = TASSEL_2 + MC_1 + ID_3;	// source SMCLK, up mode, /8 clock divider
	TA1CCTL1 = OUTMOD_7;		// reset/set - starts high
	TA1CCTL2 = OUTMOD_7;		// reset/set - starts high
	
	init_heartbeat(10000);	// 1 sec period
	init_i2c_slave(I2C_OWN_ADDR);		

	CLEAR_BIT8(P2DIR, 1);		// set P2.1 as high-impedance input (PWM out disabled)
	CLEAR_BIT8(P2DIR, 4);		// set P2.4 as high-impedance input (PWM out disabled)


	_BIS_SR(GIE); 						   // Enable global interrupt

	
	while(1) {  
	}  // while
} // main()




void	RX_callback(unsigned char reg, unsigned char* data, short int data_len)
{
	if(reg == 0) { // enable register
		registers[reg] = data[0];
		if(data[0] & 0x01) { // 0 bit is set, enable output
			SET_BIT8(P2DIR, 1);		// output
			SET_BIT8(P2SEL, 1);		// set P2.1 as timer 1.1 out
		} else { // disable output
			CLEAR_BIT8(P2SEL, 1);	// set P2.1 as normal I/O
			CLEAR_BIT8(P2DIR, 1);		// input
		}

		if(data[0] & 0x02) { // 1 bit is set, enable output
			SET_BIT8(P2DIR, 4);		// output
			SET_BIT8(P2SEL, 4);		// set P2.4 as timer 1.2 out
		} else { // disable output
			CLEAR_BIT8(P2SEL, 4);	// set P2.4 as normal I/O
			CLEAR_BIT8(P2DIR, 4);		// input
		}

	} else if(reg == 1) { // set PWM 1
		registers[reg] = data[0];
		TA1CCR1 = data[0];
	} else if(reg == 2) { //set PWM 2
		registers[reg] = data[0];
		TA1CCR2 = data[0];
	}
}

short int	TX_callback(unsigned char reg, unsigned char* data)
{
	short int data_len = 1;  // in this one we always return just 1 byte

	if(reg <= NUM_REG) {  // reg is unsigned...
		data[0] = registers[reg];
	} else {
		data[0] = 0xff;  // this is an error, just return whatever
	}

	return data_len;
}
